import datetime

from django.shortcuts import render

# Create your views here.
from django.conf import settings
from django.shortcuts import redirect
from rest_framework import views
from rest_framework import mixins
from rest_framework import viewsets
from rest_framework import permissions
from rest_framework.response import Response
from rest_framework.authentication import SessionAuthentication
from rest_framework_jwt.authentication import JSONWebTokenAuthentication

from utils.permissions import IsOwnerOrReadOnly
from utils.alipay import AliPay
from .models import ShoppingCart, OrderInfo, OrderGoods
from .serializers import ShoppingCartSerializer, ShoppingCartDetailSerializer
from .serializers import OrderSerializer, OrderDetailSerializer


class ShoppingCartViewSet(viewsets.ModelViewSet):
    """
    购物车功能
    list:
        获取购物车详情
    create:
        加入购物车
    update:
        更新购物车记录
    delete:
        删除购物车记录
    """
    permission_classes = (permissions.IsAuthenticated, IsOwnerOrReadOnly,)
    authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication,)
    # serializer_class = ShoppingCartSerializer
    lookup_field = 'goods_id'

    def get_serializer_class(self):
        if self.action == 'list':
            return ShoppingCartDetailSerializer
        else:
            return ShoppingCartSerializer

    def get_queryset(self):
        return ShoppingCart.objects.filter(user=self.request.user)

    def perform_create(self, serializer):
        # 将商品加入购物车需要减库存
        obj_shopping_cart = serializer.save()
        goods = obj_shopping_cart.goods
        goods.goods_num -= obj_shopping_cart.nums
        goods.save()

    def perform_destroy(self, instance):
        # 将商品从购物车删除，把库存加回来
        goods = instance.goods
        goods.goods_num += instance.nums
        goods.save()
        instance.delete()

    def perform_update(self, serializer):
        # 修改购物车，可能时增加商品数量，也可能是减少商品数量，根据情况增减商品库存
        existed_record = ShoppingCart.objects.get(id=serializer.instance.id)
        existed_nums = existed_record.nums
        # 获取保存之后的值
        saved_record = serializer.save()
        nums = saved_record.nums - existed_nums
        goods = saved_record.goods
        goods.goods_num -= nums
        goods.save()


class OrderViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, mixins.CreateModelMixin, mixins.DestroyModelMixin, viewsets.GenericViewSet):
    """
    订单管理
    list:
        获取个人订单
    delete:
        删除订单
    create:
        新增订单
    """
    permission_classes = (permissions.IsAuthenticated, IsOwnerOrReadOnly,)
    authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication,)
    # serializer_class = OrderSerializer

    def get_queryset(self):
        return OrderInfo.objects.filter(user=self.request.user)

    def get_serializer_class(self):
        if self.action == "retrieve":
            return OrderDetailSerializer
        return OrderSerializer

    def perform_create(self, serializer):
        """
        生成订单需要。在订单表OrderInfo中插入一条数据
        清空购物车，并将购物车中的商品变为订单商品
        """
        order = serializer.save()
        shopping_carts = ShoppingCart.objects.filter(user=self.request.user)
        for shopping_cart in shopping_carts:
            obj_order_goods = OrderGoods()
            obj_order_goods.goods = shopping_cart.goods
            obj_order_goods.goods_num = shopping_cart.nums
            obj_order_goods.order = order
            obj_order_goods.save()
            shopping_cart.delete()
        return order


class AlipaiView(views.APIView):
    def get(self, request):
        """
        处理支付宝的return_url返回。
        这个在支付宝的官方文档查看说明
        :param request:
        :return:
        """
        # 获取支付宝返回的数据
        processed_dict = {}
        for key, value in request.GET.items():
            processed_dict[key] = value

        sign = processed_dict.pop('sign', None)

        alipay = AliPay(
            appid=settings.ALI_APPID,
            app_notify_url=settings.ALI_APP_NOTIFY_URL,  # 异步的
            app_private_key_path=settings.PRIVATE_KEY_PATH,
            alipay_public_key_path=settings.ALI_PUB_KEY_PATH,  # 支付宝的公钥，验证支付宝回传消息使用，不是你自己的公钥,
            debug=settings.ALI_IS_DEBUG,  # 默认False,
            return_url=settings.ALI_RETURN_URL  # 同步的
        )

        verify_res = alipay.verify(processed_dict, sign)

        if verify_res:
            order_sn = processed_dict.get('out_trade_no', None)  # 商户网站的唯一id
            trade_no = processed_dict.get('trade_no', None)  # 支付宝生成的交易流水id
            trade_status = processed_dict.get('trade_status', None)  # 交易状态

            existed_orders = OrderInfo.objects.filter(order_sn=order_sn)
            for existed_order in existed_orders:
                # 支付完成后，记录商品售卖的数量
                order_goodses = existed_order.goods.all()
                for order_goods in order_goodses:
                    goods = order_goods.goods
                    goods.sold_num += order_goods.goods_num
                    goods.save()

                existed_order.pay_status = trade_status
                existed_order.trade_no = trade_no
                existed_order.pay_time = datetime.datetime.now()
                existed_order.save()
            # return Response("success")  # 需要向支付宝返回success,否则支付宝会一直向这个接口发数据

            # 支付完成后跳转回首页

            response = redirect("index")
            response.set_cookie("nextPath", "pay", max_age=2)  # 这个是vue中设置的，通过判断nextPath是否为pay进行操作
            return response
        else:
            response = redirect("index")
            return response

    def post(self, request):
        """
        处理支付宝的notify_url返回。
        这个在支付宝的官方文档查看说明
        :param request:
        :return:
        """
        # 获取支付宝返回的数据
        processed_dict = {}
        for key, value in request.POST.items():
            processed_dict[key] = value

        sign = processed_dict.pop('sign', None)

        alipay = AliPay(
            appid="2016092500594635",
            app_notify_url=settings.ALI_APP_NOTIFY_URL,  # 异步的
            app_private_key_path=settings.PRIVATE_KEY_PATH,
            alipay_public_key_path=settings.ALI_PUB_KEY_PATH,  # 支付宝的公钥，验证支付宝回传消息使用，不是你自己的公钥,
            debug=True,  # 默认False,
            return_url=settings.ALI_RETURN_URL  # 同步的
        )

        verify_res = alipay.verify(processed_dict, sign)

        if verify_res:
            order_sn = processed_dict.get('out_trade_no', None)  # 商户网站的唯一id
            trade_no = processed_dict.get('trade_no', None)  # 支付宝生成的交易流水id
            trade_status = processed_dict.get('trade_status', None)  # 交易状态

            existed_orders = OrderInfo.objects.filter(order_sn=order_sn)
            for existed_order in existed_orders:
                existed_order.pay_status = trade_status
                existed_order.trade_no = trade_no
                existed_order.pay_time = datetime.datetime.now()
                existed_order.save()

            return Response("success")  # 需要向支付宝返回success,否则支付宝会一直向这个接口发数据


